Skip to main content

使用Gin作为 HTTP Server

各自优点

选择使用 Kratos 的 HTTP 服务还是使用 Gin 作为 HTTP 服务取决于项目需求和偏好。这两种方法都有各自的优势和适用场景。

使用 Kratos 官方的 HTTP 服务:

  1. 一体化: Kratos 提供了完整的微服务开发框架,它的 HTTP 服务与其他组件(如RPC服务、数据存储等)紧密集成,可以更轻松地构建整体功能。
  2. 内置特性: Kratos 的 HTTP 服务内置了一些特性,如链路追踪、健康检查、中间件等,可以更方便地管理和监控服务。
  3. 标准化: Kratos 是一个遵循标准化设计原则的框架,有一定的最佳实践指导,可以帮助编写更一致、可维护的代码。

使用 Gin 作为 HTTP 服务:

  1. 灵活性: 轻量级的框架,可以根据需求自由选择中间件和插件,以满足特定的业务需求。
  2. 生态系统: 拥有丰富的第三方插件和库,可以方便地扩展功能,例如验证、API文档生成等。
  3. 开发速度: Gin 通常被认为是一个开发速度较快的框架,适用于快速构建原型和小规模项目。

如何选择?

考虑团队熟悉度、项目规模、性能要求、扩展性等。如果已经使用了 Kratos 的其他组件,使用它的官方HTTP服务可能会更加方便。

如果更倾向于手动控制和定制,或者需要使用其他Gin提供的特性,那么使用Gin是一个不错的选择。

用法

由于使用了 gin 作为路由处理,那么就不需要在protobuf定义google.api.http这个option

  1. 在不影响现有的架构情况下添加 HTTP Server时, 添加一个用户接口层interfaces目录(DDD 思想)
  2. 通过gin写路由与处理请求和响应
  3. kratos集成
  4. 注入gin路由用例到wire

规范分层, 编写服务

  1. internal添加interfaces目录, 编写gin服务
  2. 定义 gin 服务
  3. 定义路由
  4. 返回 gin 服务 routes.go
package interfaces

func RegisterHTTPServer () *gin.Engine{
r := gin.Default()
r.Any("/", us.SayHi)

return r
}

编写路由用例, 响应与处理

  1. 定义一个路由用例的结构体,与Service层交互
  2. 编写该路由的用例, 实现该路由用例的结构体
  3. 编写路由

interfaces/sayhi.go

package interfaces

type SayHiUseCase struct {
sayHiService *service.SayHiService
log *log.Helper
}

func NewSayHiUseCase(sh *service.SayHiService, logger log.Logger) *SayHiUseCase{
return &SayHiUseCase{
sayHiService: sh,
log: logger.NewHelper(logger)
}
}

func SayHi (c *gin.Context){
c.JSON(200,gin.H{
"msg":"OK",
})
}

与 Kratos 集成

  1. service/http.go中注册路由
  2. 在函数NewHTTPServer中添加在interfaces用户接口层编写的路由用例参数
  3. 调用interfaces用户接口层的注册方法RegisterHTTPServer注入到 srv
package server

import (
"github.com/go-kratos/kratos/v2/middleware/logging"
"tiktok/internal/conf"
"tiktok/internal/interfaces"
"tiktok/internal/service"

"github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/middleware/recovery"
"github.com/go-kratos/kratos/v2/transport/http"
)

// NewHTTPServer new an HTTP server.
func NewHTTPServer(c *conf.Server, userRouter *interfaces.UserUseCase, user *service.UserService, logger log.Logger) *http.Server {
// http server

var opts = []http.ServerOption{
http.Middleware(
recovery.Recovery(),
logging.Server(logger),
),
}
if c.Http.Network != "" {
opts = append(opts, http.Network(c.Http.Network))
}
if c.Http.Addr != "" {
opts = append(opts, http.Address(c.Http.Addr))
}
if c.Http.Timeout != nil {
opts = append(opts, http.Timeout(c.Http.Timeout.AsDuration()))
}
srv := http.NewServer(opts...)
srv.HandlePrefix("/v1/user", interfaces.RegisterHTTPServer(userRouter))
// user.RegisterUserHTTPServer(srv, user)
return srv
}

编写ProviderSet

interfaces用户接口层编写ProviderSet

interfaces/interface.go

package interfaces

import "github.com/google/wire"

var ProviderSet = wire.NewSet(NewUserUseCase)

注入到 wire 中

cmd/<project>/wire.go

//go:build wireinject
// +build wireinject

// The build tag makes sure the stub is not built in the final build.

package main

import (
"tiktok/internal/biz"
"tiktok/internal/conf"
"tiktok/internal/data"
"tiktok/internal/server"
"tiktok/internal/service"

"github.com/go-kratos/kratos/v2"
"github.com/go-kratos/kratos/v2/log"
"github.com/google/wire"
)

// wireApp init kratos application.
func wireApp(*conf.Server, *conf.Database, log.Logger) (*kratos.App, func(), error) {
panic(wire.Build(server.ProviderSet, data.ProviderSet, biz.ProviderSet, service.ProviderSet, interfaces.ProviderSet, newApp))
}

测试

  1. 进入到cmd/<project>目录
  2. 在该目录使用终端执行wire
  3. 启动项目, 测试接口是否正常

https://blog.csdn.net/m0_47404181/article/details/118339724